(2024/04/06更新) 因應React在18後更新了許多不同的語法,更新後的教學之後將陸續放在 新的blog 中,歡迎讀者到該處閱讀,我依然會回覆這邊的提問
目前的menu雖然對外部使用者可以客製化的內容變多了,但仍然有一個缺點:
「元件內部的架構被綁死,很不彈性。」
什麼意思? 更詳細來說, 目前如果要使用我們的元件,就一定會生出一個title + button + 摺疊區 + ul + li 的UI。但如果今天我們希望摺疊區內的不要是ul + li呢? 這樣是不是要寫一個新的menu?
這個時候,我們只要再繼續拆分架構,就能讓這個Menu被獨立共用,而不是包死 ul + li。
本來我們設定摺疊區內元素的方法,是透過把參數的文字array,拿去加工成li元素,再丟入摺疊區:
function Menu(menuItemWording){
(省略)
//列表的container
let menu = document.createElement('ul');
menu.setAttribute('class',"menu")
menuItemWording.forEach((item)=>{
let menuItem = document.createElement('li');
menuItem.setAttribute('class',"menu-item");
menuItem.textContent = item;
menu.appendChild(menuItem);
});
//控制「列表的container」開關的按鈕
let menuBtn = document.createElement('button');
(省略)
}
現在我們來讓丟入摺疊區的元素也變成參數,這樣不管在參數array丟入啥,都能顯示在元件中:
function Menu(menuItem){
(省略)
//列表的container
let menu = document.createElement('ul');
menu.setAttribute('class',"menu")
menuItem.forEach((item)=>{
menu.appendChild(item.getDOMItem());
});
//控制「列表的container」開關的按鈕
let menuBtn = document.createElement('button');
(省略)
}
接著我們把原本用來製作menuItem的code獨立出來模組化,然後在index.js統一做資料加工,並把加工結果丟入menu當參數。
function MenuItem(wording){
let menuItem = document.createElement('li');
menuItem.setAttribute('class',"menu-item");
menuItem.textContent = wording;
this.getDOMItem = () => menuItem;
}
// 文字
let menuItemWording=[
"Like的發問",
"Like的回答",
"Like的文章",
"Like的留言"
];
let menuItem = menuItemWording.map((wording) => new MenuItem(wording));
let menuInstance = new Menu(menuItem);
(以下略)
然後要記得引入新創建的檔案
</body>
<script src="./js/component/menuItem.js" type="text/javascript"></script>
<script src="./js/component/menu.js" type="text/javascript"></script>
<script src="./js/index.js" type="text/javascript"></script></script>
</html>
現在回過頭來,你會發現幾個主要的差別:
當然,這裡可能還有更多可以增進的地方,但相信你在這幾天後,能夠體會到前端程式的元件化過程是什麼樣子。
未來在進入React.js時,回過頭來看這幾篇,你會發現React架構有包含許多類似的概念。